package com.ds.infrastructure.hyperspace.container.flow.operation;

import com.ds.infrastructure.hyperspace.common.StateEnum;
import com.ds.infrastructure.hyperspace.common.flow.DuplexFlowContext;
import com.ds.infrastructure.hyperspace.container.flow.context.HyperspaceDuplexFlowContext;
import com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameWrapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufHolder;
import org.springframework.util.CollectionUtils;

import java.util.LinkedList;

/**
 * @author  Weishaoying
 */
public abstract class AbstractFlowOperation<C extends DuplexFlowContext> implements FlowOperation<C> {

    @Override
    public void interruptAndCloseContext(C duplexFlowContext, StateEnum state, String message) {
        HyperspaceDuplexFlowContext hyperspaceDuplexFlowContext = (HyperspaceDuplexFlowContext) duplexFlowContext;
        LinkedList<Object> referDataLinkList = hyperspaceDuplexFlowContext.getReferDataLinkList();
        if (!CollectionUtils.isEmpty(referDataLinkList)) {
            for (Object referData : referDataLinkList) {
                hyperspaceDuplexFlowContext.getEntryProtocolAdapter().releaseData(referData);
            }
        }
        if (hyperspaceDuplexFlowContext.getEntryProtocolAdapter() != null) {
            hyperspaceDuplexFlowContext.getEntryProtocolAdapter()
                    .releaseData(hyperspaceDuplexFlowContext.getRequestStartState());
        }
        if (duplexFlowContext.isClosed()) {
            return;
        }

        duplexFlowContext.close();
        duplexFlowContext.setInterruptState(state, message);
        handleOutputComplete(duplexFlowContext);
    }

    @Override
    public int calculateMessageSize(Object msg) {
        if (msg instanceof ByteBuf) {
            return ((ByteBuf) msg).readableBytes();
        } else if (msg instanceof ByteBufHolder) {
            return ((ByteBufHolder) msg).content().readableBytes();
        } else if (msg instanceof HyperspaceHttp2FrameWrapper) {
            return ((HyperspaceHttp2FrameWrapper) msg).payloadSize();
        }
        return 1;
    }

}
